/*
 *                        .::::.
 *                      .::::::::.
 *                     :::::::::::
 *                  ..:::::::::::'
 *               '::::::::::::'
 *                 .::::::::::
 *            '::::::::::::::..
 *                 ..::::::::::::.
 *               ``::::::::::::::::
 *                ::::``:::::::::'        .:::.
 *               ::::'   ':::::'       .::::::::.
 *             .::::'      ::::     .:::::::'::::.
 *            .:::'       :::::  .:::::::::' ':::::.
 *           .::'        :::::.:::::::::'      ':::::.
 *          .::'         ::::::::::::::'         ``::::.
 *      ...:::           ::::::::::::'              ``::.
 *     ````':.          ':::::::::'                  ::::..
 *                        '.:::::'                    ':'````..
 *
 * @Author: ls
 * @Date: 2020-12-16 11:53:23
 * @LastEditTime: 2020-12-18 10:43:24
 * @LastEditors: Please set LastEditors
 * @Description: 圆周运动 - 时间,旋转角度,圆心位置
 * @FilePath: \circularMotion\assets\script\moveCircle.js
 */

// 两点之间距离
let dist = function (p1, p2) {
    var a = p2.x - p1.x;
    var b = p2.y - p1.y;
    return Math.sqrt(a * a + b * b);
};

cc.MoveCircleBy = cc.Class({
    name: 'cc.MoveCircleBy',
    extends: cc.ActionInterval,

    statics: {
        _reverse: false,
    },

    ctor: function (duration, deltaAngle, deltaPos, deltaY) {
        // 半径
        this._radius = 0;
        // 目标角度
        this._deltaAngle = 0;
        // 开始角度
        this._startAngle = 0;
        // 开始位置
        this._startPosition = cc.v2(0, 0);
        // 圆心位置
        this._centerPosition = cc.v2(0, 0);

        if (deltaAngle !== undefined) {
            deltaAngle *= cc.MoveCircleBy._reverse ? 1 : -1;
            this.initWithDuration(duration, deltaAngle, deltaPos, deltaY);
        }
    },

    // Initializes the action.
    initWithDuration: function (duration, deltaAngle, deltaPos, deltaY) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration, deltaPos, deltaY)) {
            this._deltaAngle = deltaAngle;
            if (deltaPos.x !== undefined) {
                deltaY = deltaPos.y;
                deltaPos = deltaPos.x;
            }
            this._centerPosition.x = deltaPos;
            this._centerPosition.y = deltaY;
            return true;
        }
        return false;
    },

    clone: function () {
        var action = new cc.MoveCircleBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._deltaAngle, this._centerPosition);
        return action;
    },

    startWithTarget: function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._startAngle = target.angle;

        this._startPosition.x = target.x;
        this._startPosition.y = target.y;
        this._radius = dist(this._centerPosition, this._startPosition);
    },

    update: function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            // cc.log(this._deltaAngle * dt);

            // 根据半径和弧度求出圆一点坐标
            let x = -this._radius * Math.sin(((this._startAngle + this._deltaAngle * dt) / 180) * Math.PI);
            let y = this._radius * Math.cos(((this._startAngle + this._deltaAngle * dt) / 180) * Math.PI);
            // 更新坐标
            this.target.x = this._centerPosition.x + x;
            this.target.y = this._centerPosition.y + y;
            this.target.angle = this._startAngle + this._deltaAngle * dt;
        }
    },

    reverse: function () {
        var action = new cc.MoveCircleBy();
        action.initWithDuration(this._duration, -this._deltaAngle, this._centerPosition);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
});

/**
 * !#zh 顺时针移动,旋转指定的角度。
 * @method moveCircleBy
 * @param {Number} duration duration in seconds
 * @param {Number} deltaAngle deltaAngle in degrees
 * @param {Vec2|Number} deltaPos deltaPos in center position
 * @param {Number} [deltaY]
 * @return {ActionInterval}
 * @example
 * example
 * var actionBy = new cc.MoveCircleBy(2, 360, cc.v(0, 0));
 */
cc.moveCircleBy = function (duration, deltaAngle, deltaPos, deltaY) {
    return new cc.MoveCircleBy(duration, deltaAngle, deltaPos, deltaY);
};

/* ----- ----- ----- ----- ----- 分割线 ----- ----- ----- ----- ----- */

cc.MoveCircleTo = cc.Class({
    name: 'cc.MoveCircleTo',
    extends: cc.ActionInterval,

    statics: {
        _reverse: false,
    },

    ctor: function (duration, dstAngle, deltaPos, deltaY) {
        this._angle = 0;
        this._radius = 0;
        this._dstAngle = 0;
        this._startAngle = 0;
        this._startPosition = cc.v2(0, 0);
        this._centerPosition = cc.v2(0, 0);

        dstAngle !== undefined && this.initWithDuration(duration, dstAngle, deltaPos, deltaY);
    },

    // Initializes the action.
    initWithDuration: function (duration, dstAngle, deltaPos, deltaY) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._dstAngle = dstAngle;
            if (deltaPos.x !== undefined) {
                deltaY = deltaPos.y;
                deltaPos = deltaPos.x;
            }
            this._centerPosition.x = deltaPos;
            this._centerPosition.y = deltaY;
            return true;
        }
        return false;
    },

    clone: function () {
        var action = new cc.MoveCircleTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._dstAngle, this._centerPosition);
        return action;
    },

    startWithTarget: function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        let startAngle = target.angle % 360;
        let angle = cc.MoveCircleTo._reverse ? this._dstAngle - startAngle : this._dstAngle + startAngle;
        if (angle > 180) angle -= 360;
        if (angle < -180) angle += 360;
        this._startAngle = startAngle;
        this._angle = cc.MoveCircleTo._reverse ? angle : -angle;

        this._startPosition.x = target.x;
        this._startPosition.y = target.y;
        this._radius = dist(this._centerPosition, this._startPosition);
    },

    reverse: function () {
        cc.logID(1016);
    },

    update: function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            this.target.angle = this._startAngle + this._angle * dt;

            // cc.log(this._angle * dt);
            // 根据半径和弧度求出圆一点坐标
            let x = -this._radius * Math.sin(((this._startAngle + this._angle * dt) / 180) * Math.PI);
            let y = this._radius * Math.cos(((this._startAngle + this._angle * dt) / 180) * Math.PI);
            // 更新坐标
            this.target.x = this._centerPosition.x + x;
            this.target.y = this._centerPosition.y + y;
        }
    },
});

/**
 * !#zh 旋转到目标角度，通过逐帧修改它的 angle 属性，旋转方向将由最短的角度决定。
 * @method rotateTo
 * @param {Number} duration duration in seconds
 * @param {Number} dstAngle dstAngle in degrees.
 * @param {Vec2|Number} deltaPos deltaPos in center position
 * @param {Number} [deltaY]
 * @return {ActionInterval}
 * @example
 * example
 * var actionTo = new cc.moveCircleTo(2, 360, cc.v(0, 0));
 */
cc.moveCircleTo = function (duration, dstAngle, deltaPos, deltaY) {
    return new cc.MoveCircleTo(duration, dstAngle, deltaPos, deltaY);
};
